/**
 * 
 */
package org.istt.dao.hibernate;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.istt.dao.MenuDao;
import org.istt.domain.Menu;
import org.istt.domain.MenuTree;
import org.istt.model.MenuTreeBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

/**
 * @author NDTHO
 *
 */
@Repository("menuDao")
public class MenuDaoHibernate extends BaseDaoHibernate<Menu, Long> implements MenuDao {
	Log logger = LogFactory.getLog(MenuDaoHibernate.class);
	@Autowired
	public MenuDaoHibernate(SessionFactory sessionFactory) {
		super(sessionFactory);
	}
	
	public List<Menu> getSubMenuById(Long mainmenuId){
		List<Menu> lstMnu = new ArrayList<Menu>();
		
		
		return lstMnu;
	}
	
	@SuppressWarnings("unchecked")
	public List<Menu> getAll(){
		List<Menu> lstResult = new ArrayList<Menu>();
		lstResult = (List<Menu>)hibernateTemplate.execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,	SQLException {
						Criteria criteria = session.createCriteria(Menu.class);
						criteria.addOrder(Order.asc("position"));
						return criteria.list();
			}
		});
		
		return lstResult;
	}
	@SuppressWarnings("unchecked")
	public List<Menu> getFatherMenu(){
		List<Menu> lstResult = new ArrayList<Menu>();
		lstResult = (List<Menu>)hibernateTemplate.execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,	SQLException {
				Criteria criteria = session.createCriteria(Menu.class);
				criteria.add(Restrictions.eq("isFather", true));
				return criteria.list();
			}
		});
		
		return lstResult;
	}
	
	public List<MenuTreeBean> getMenuTrees(){
		List<MenuTreeBean> lstMnu = new ArrayList<MenuTreeBean>();
		
		List<Menu> lstMenu = getAll();
		if(lstMenu.size()!=0){
			Hashtable<Long, Menu> lstMenuTree = new Hashtable<Long, Menu>();
			
			for (int i = 0; i < lstMenu.size(); i++) {
				Menu mnu = lstMenu.get(i);
				lstMenuTree.put(mnu.getId(), mnu);
				if(mnu.getIsFather()){
					MenuTreeBean mnuBean = new MenuTreeBean();
					mnuBean.setMainMenu(mnu);
					lstMnu.add(mnuBean);
				}
			}
			
			if(lstMnu.size()!=0){
				for (int j = 0; j < lstMnu.size(); j++) {
					MenuTreeBean mnuBean = lstMnu.get(j);
					List<Menu> lstSubMenu = new ArrayList<Menu>();
					// Gets sub-menu
					if(mnuBean.getMainMenu().getMenuTrees()!=null && mnuBean.getMainMenu().getMenuTrees().size()!=0){
						Set<MenuTree> lstSubMenuTmp = mnuBean.getMainMenu().getMenuTrees();
						Iterator<MenuTree> it = lstSubMenuTmp.iterator();
						while (it.hasNext()) {
							MenuTree mnu = it.next();
							Menu subMenu = lstMenuTree.get(mnu.getChildMenuId());
							lstSubMenu.add(subMenu);
						}
						// Sort list sub-menu before adding to main-menu
						Collections.sort(lstSubMenu, POSITION_ORDER);

						mnuBean.setLstSubMenu(lstSubMenu);
					}
				}
			}
		}
		return lstMnu;
	}
	
	static final Comparator<Menu> POSITION_ORDER =  new Comparator<Menu>() {
		public int compare(Menu e1, Menu e2) {
			return e1.getPosition().compareTo(e2.getPosition());
		}
	};


	@Override
	public Menu getMenuById(Long id) {
		
		Menu menu = findById(id, false);
        if (menu == null) {
            throw new ObjectRetrievalFailureException(Menu.class, id);
        }
        return menu;
	}
	
	public void saveMenu(Menu menu) {
        makePersistent(menu);

        if (logger.isDebugEnabled()) {
            logger.debug("menuId set to: " + menu.getId());
        }
        
    }

    public void removeMenu(Long id) {
    	makeTransient(getMenuById(id));
    }
	
}
